#include "Stream.h"
#include "Debug.h"
#include "../PreDefine.h"
//#include "IPLWrappingFunctions.h"
///////////////////////////////////////////////////////////////////
//CFileStream
//global functions
//methods
CFileStream::CFileStream() : miLength(0), mBuffer(NULL), miOffset(0)
{
	mIsOpen = false;
}

CFileStream::~CFileStream(void)
{
	//if (mIsOpen)
		Close();
}

bool CFileStream::OpenForRead(const char * filename)
{
	char path[TEXT_FILENAME_SIZE];
	getResourcePath(filename, path);
	if (strlen(path) > TEXT_FILENAME_SIZE)
	{
		logToOut("filename too long!!!!");
		ASSERT(false);
	}
	mFileID = fopen(path, "rb");
	ASSERT(mFileID != NULL);

	// RUIZD: Return if fails
	if (mFileID == NULL)
	{
		logToOut("failed to open file %s!", path);
		logToFileClose();
		return false;
	}
	else
	{
		logToOut("file open: %s", path);
	}

	mIsOpen = (mFileID != NULL);

	// RUIZD: [Added] Alloc buffer and read all the file
	int fileSize = GetSize();
	mBuffer = GL_NEW char[fileSize];
	miLength = fileSize;

	// RUIZD: [Added] Read the file
	fread(mBuffer, fileSize, 1, mFileID);
	fclose(mFileID);

	return mIsOpen;
}

bool CFileStream::OpenForWrite(const char * filename)
{
	mFileID = fopen(filename, "wb");
	mIsOpen = (mFileID != NULL);
	return mIsOpen;
}

void CFileStream::Close()
{
	// RUIZD: Remove the buffer
	if (mBuffer != NULL)
	{
		SAFE_DELETE(mBuffer);
	}

	//if (mIsOpen)
	//	fclose(mFileID);

	mIsOpen = false;
}

bool CFileStream::Read(void *data, unsigned long len)
{
	ASSERT(data != NULL);
	return (fread(data, len, 1, mFileID) != 0);
}

bool CFileStream::Write(void *data, unsigned long len)
{
    ASSERT(data != NULL);
 	return (fwrite(data, len, 1, mFileID) == len);
}

long CFileStream::GetSize()
{
	if (!mIsOpen) return -1;

	// Save the current position
	long curpos = ftell(mFileID);

	// Move to the last byte of the file
	fseek(mFileID, 0, SEEK_END);

	// Get the position
	long pos = ftell(mFileID);

	// Return to the original position
	fseek(mFileID, curpos, SEEK_SET);

	// Return the size of the file
	return pos + 1;
}

bool CFileStream::Seek(long offset, int origin)
{
	return (fseek(mFileID, offset, origin) == 0);

}

// -------------------------------------------------------------
char CFileStream::_AppPath[TEXT_FILENAME_SIZE];
void CFileStream::setAppPath(char *path)
{
	strcpy(_AppPath, path);
}

// -------------------------------------------------------------
void CFileStream::getResourcePath(const char *res, char *out)
{
#if defined WIN32 || defined __MACOS__
	sprintf(out, "%s", res);
#else
	sprintf(out, "%s/%s", _AppPath, res);
#endif
}

/////////////////////////////////////////////////////////
//CMemoryStream
//

CMemoryStream::CMemoryStream(char* buf, unsigned long size) 
: mpData(buf)
, miPosition(0)
, miLength(size)
, mbNeedFreeBuffer(false)
{
}

void CMemoryStream::Attach(CFileStream& fs)
{
	mpData = fs.mBuffer;
	miLength = fs.miLength;
	SetPosition(0);
}

void CMemoryStream::AttachCopy(CFileStream& fs)
{
	ReleaseData();
	mpData = GL_NEW char[fs.miLength];
	MEMCPY(mpData, fs.mBuffer, fs.miLength);
	miLength = fs.miLength;
	SetPosition(0);
}

void CMemoryStream::ReleaseData()
{
	if(mpData != NULL)
	{
		SAFE_DELETE(mpData);
	}
}


CMemoryStream::~CMemoryStream()
{
	// RUIZD: The buffer will be free in the FileStream Close method
	//if (mbNeedFreeBuffer)
	//	SAFE_DELETE(mpData);
	mpData = NULL;
}

int CMemoryStream::Read(void* out, long size)
{
	ASSERT(out);
	ASSERT(mpData);
	
	if(miPosition + size < 0)
	{
		return 0;
	}
	else if(miPosition + size >= miLength)
	{
		size = miLength - miPosition;
	}
	
	if(size > 0)
	{	
		memcpy(out, mpData + miPosition, (unsigned long)size);
	}

	miPosition += size;
	
	return size;
}

int CMemoryStream::Write(void* in,  long  size)
{
	ASSERT(in);
	ASSERT(mpData);

	if(miPosition + size < 0)
	{
		return 0;
	}
	else if(miPosition + size >= miLength)
	{
		size = miLength - miPosition;
	}

	if(size > 0)
	{	
		memcpy(mpData + miPosition, in, (unsigned long)size);
	}

	miPosition += size;

	return size;
}

int CMemoryStream::Seek(int offset, int origin)
{
	ASSERT(mpData);

	if(origin == SEEK_CUR)
	{

	}
	else if(origin == SEEK_SET)
	{
		SetPosition(0);
	}
	else if(origin == SEEK_END)
	{
		SetPosition(miLength - 1);
	}
	else
	{
		return 0;
	}
	
	return Seek(offset);
}

int CMemoryStream::SetPosition(int pos)
{
	ASSERT(mpData);

	if(pos < 0 ||  pos >= miLength)
	{
		return 0;
	}

	int distance = pos - miPosition;
	
	miPosition = pos;

	return distance;
}

int CMemoryStream::Seek(int offset)
{
	return SetPosition(offset);
}

unsigned char CMemoryStream::ReadUChar()
{ 
	unsigned char c; 
	Read(&c, 1); 
	return c;
}

short CMemoryStream::ReadShortBE()
{ 
	unsigned char c[2]; 
	Read(&c, 2); 
	return (c[0] << 8) | c[1];
}

short CMemoryStream::ReadShort()
{
	unsigned char c[2]; 
	Read(&c, 2); 
	return (c[1] << 8) | c[0];
}

int	CMemoryStream::ReadIntLE()
{
	unsigned char c[4]; 
	Read(&c, 4); 
	return (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0];
}